﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Net;
using System.ComponentModel;

namespace sabConn
{
    public class History : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region Properties

        private string _total_size;
        public string total_size { get { return _total_size; } set { _total_size = value; } }
        private string _month_size;
        public string month_size { get { return _month_size; } set { _month_size = value; } }
        private string _week_size;
        public string week_size { get { return _week_size; } set { _week_size = value; } }
        private List<HistoryJob> _jobs;
        public List<HistoryJob> jobs { get { return _jobs; } set { _jobs = value; } }

        #endregion Properties

        private ServerConnection m_parent;
        private XmlDocument historyxml;
        private XmlNodeList historyjobs;

        public History(ServerConnection par)
        {
            m_parent = par;
            historyxml = new XmlDocument();
            _jobs = new List<HistoryJob>();
        }

        public void update()
        {
            updateXml();
            updateHistory();
            updateHistoryJobs();
        }

        private void updateXml()
        {
            string cmdstring = m_parent.serverstring + "/sabnzbd/api?mode=history&start=START&limit=LIMIT&output=xml&apikey=" + m_parent.apikey;
            historyxml.Load(cmdstring);
        }

        private void updateHistory()
        {
            //Refreshes all Queue properties.

            XmlNodeList elements = historyxml.SelectNodes("history");

            foreach (XmlNode element in elements)
            {
                total_size = element.SelectSingleNode("total_size").InnerText;
                month_size = element.SelectSingleNode("month_size").InnerText;
                week_size = element.SelectSingleNode("week_size").InnerText;
            }
        }

        private void updateHistoryJobs()
        {
            XmlNodeList xmljobs;
            xmljobs = historyxml.SelectNodes("history/slots/slot");
            //_jobs.Clear();

            foreach (XmlNode xmljob in xmljobs)
            {
                string t_action_line = "", t_id = "", t_size_byte = "", t_nzb_name= "", t_download_time= "", t_path = "";
                string t_postproc_time= "", t_name = "", t_url= "", t_category = "", t_url_info= "";
                int i_id=0, i_download_time=0, i_postproc_time=0;
                long i_size_byte=0;


                HistoryJob t_job;
                StageLog t_log = new StageLog();
                List<string> actions;

                t_action_line = xmljob.SelectSingleNode("action_line").InnerText;
                t_id = xmljob.SelectSingleNode("id").InnerText;
                t_size_byte = xmljob.SelectSingleNode("bytes").InnerText;
                t_nzb_name = xmljob.SelectSingleNode("nzb_name").InnerText;
                t_download_time = xmljob.SelectSingleNode("download_time").InnerText;
                t_path = xmljob.SelectSingleNode("storage").InnerText;
                t_postproc_time = xmljob.SelectSingleNode("postproc_time").InnerText;
                t_name = xmljob.SelectSingleNode("name").InnerText;
                t_url = xmljob.SelectSingleNode("url").InnerText;
                t_category = xmljob.SelectSingleNode("category").InnerText;
                t_url_info = xmljob.SelectSingleNode("url_info").InnerText;

                try { i_id = int.Parse(t_id); }
                catch { }
                try { i_download_time = int.Parse(t_download_time); }
                catch { }
                try { i_postproc_time = int.Parse(t_postproc_time); }
                catch { }
                try { i_size_byte = long.Parse(t_size_byte); }
                catch { }

                //Generate a new stagelog.
                XmlNodeList txml = xmljob.SelectNodes("stage_log/slot");
                foreach (XmlNode stage in txml)
                {
                    string name;
                    name = stage.SelectSingleNode("name").InnerText;
                    XmlNodeList xactions = stage.SelectNodes("actions");
                    actions = new List<string>();
                    foreach (XmlNode a in xactions)
                    {
                        actions.Add(a.InnerText);
                    }
                    t_log.Add(new Stage(name, actions));
                }
                //Create temp job to match against list.
                t_job = _jobs.FirstOrDefault(c => c.nzb_name == t_nzb_name);
                if (t_job == null)
                {
                    t_job = new HistoryJob(t_action_line, i_id, i_size_byte, t_category, t_nzb_name, i_download_time, t_path, i_postproc_time, t_name, t_url, t_url_info, t_log);
                    jobs.Add(t_job);
                }
                OnPropertyChanged("jobs");
            }
        }
    }

    public class HistoryJob
    {
        #region Properties
        private int _id;
        public int id { get { return _id; } set { _id = value; } }
        private string _name;
        public string name { get { return _name; } set { _name = value; } }
        private long _size_byte;
        public long size_byte { get { return _size_byte; } set { _size_byte = value; } }
        private string _category;
        public string category { get { return _category; } set { _category = value; } }
        private int _download_time;
        public int download_time { get { return _download_time; } set { _download_time = value; } }
        private string _path;
        public string path { get { return _path; } set { _path = value; } }
        private int _postproc_time;
        public int postproc_time { get { return _postproc_time; } set { _postproc_time = value; } }
        private string _url;
        public string url { get { return _url; } set { _url = value; } }
        private string _url_info;
        public string url_info { get { return _url_info; } set { _url_info = value; } }
        private StageLog _stagelog;
        public StageLog stagelog { get { return _stagelog; } set { _stagelog = value; } }
        private string _action_line;
        public string action_line { get { return _action_line; } set { _action_line = value; } }
        private string _nzb_name;
        public string nzb_name { get { return _nzb_name; } set { _nzb_name = value; } }
        #endregion Properties

        public HistoryJob(string action_line, int id, long size_byte, string category, string nzb_name, int download_time, string path,
            int postproc_time, string name, string url, string url_info, StageLog stagelog)
        {
            _action_line = action_line;
            _id = id;
            _size_byte = size_byte;
            _category = category;
            _nzb_name = nzb_name;
            _download_time = download_time;
            _path = path;
            _postproc_time = postproc_time;
            _name = name;
            _url = url;
            _url_info = url_info;
            _stagelog = stagelog;
        }

        private void initStageLog()
        {

        }
    }

    public class StageLog
    {
        private List<Stage> _stages;
        public List<Stage> stages { get { return _stages; } set { _stages = value; } }
        int position = -1;

        public StageLog()
        {
            stages = new List<Stage>();
        }

        public void Add(Stage s)
        {
            stages.Add(s);
        }

        public Stage Find(string name)
        {
            try
            {
                foreach(Stage s in stages)
                {
                    if(s.name == name)
                    {
                        return s;
                    }
                }
            }
            catch
            {
                return new Stage("null", new List<string>());
            }
            return new Stage("null", new List<string>());
        }

        public string getStageInfo(string name)
        {
            try
            {
                foreach (Stage s in stages)
                {
                    if (s.name == name)
                    {
                        string retval="";
                        foreach (string i in s.actions)
                        {
                            retval = retval + i + Environment.NewLine;
                        }
                        return retval;
                    }
                }
            }
            catch
            {
                return "null";
            }
            return "null";
        }

    }

    public class Stage
    {
        private string _name;
        public string name { get { return _name; } set { _name = value; } }
        private List<string> _actions;
        public List<string> actions { get { return _actions; } set { _actions = value; } }

        public Stage(string name, List<string> actions)
        {
            _name = name;
            _actions = actions;
        }
    }
}
